﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
using BrainTechLLC;
using BrainTechLLC.ThreadSafeObjects;
using BrainTechLLC.Silverlight.Controls;
using System.Diagnostics;
using BrainTechLLC.Silverlight.InputControls;

namespace BrainTechLLC.Silverlight.ClientApplication
{
    public partial class ShowPropertiesControl : BaseDataVisualizer, IUICanOpenClose, ISingleItemDataVisualizer
    {
        public override void SetVisualizedData(DataVisualizer vis, object o) { Properties = o as ObservableCollection<IdentifierAndValue>; base.SetVisualizedData(vis, o); }
        public Type VisualizeType { get { return typeof(IdentifierAndValue); } }
        public string VisualizerName { get { return "ShowPropertiesControl"; } }

        public static readonly DependencyProperty OwnerProperty = DependencyProperty.Register(
            "Owner", typeof(object), typeof(ShowPropertiesControl), new PropertyMetadata(null, new PropertyChangedCallback(OwnerChanged)));

        public object Owner
        {
            get { return (object)GetValue(OwnerProperty); }
            set { SetValue(OwnerProperty, value); }
        }

        private static void OwnerChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            HandleChange<object>(d, e, (t, val) => t.Owner = val);
        }

        public static readonly DependencyProperty PropertiesProperty = DependencyProperty.Register(
            "Properties", typeof(ObservableCollection<IdentifierAndValue>), typeof(ShowPropertiesControl), new PropertyMetadata(null, new PropertyChangedCallback(PropertiesChanged)));

        public ObservableCollection<IdentifierAndValue> Properties
        {
            get { return (ObservableCollection<IdentifierAndValue>)GetValue(PropertiesProperty); }
            set { SetValue(PropertiesProperty, value); }
        }

        private static void PropertiesChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            HandleChange<ObservableCollection<IdentifierAndValue>>(d, e, (t, val) => t.Properties = val);
        }

        public static void HandleChange<T2>(DependencyObject d, DependencyPropertyChangedEventArgs e, Action<ShowPropertiesControl, T2> action)
        {
            d.HandleChange<ShowPropertiesControl, T2>(e, action, (t) => t.UpdateBindings());
        }

        public override void OnSaveData()
        {
            base.OnSaveData();
            SaveProps();
        }

        public override void UpdateBindings()
        {
            if (Properties != null)
            {
                if (lstProps != null && lstProps.ItemsSource != Properties)
                    lstProps.ItemsSource = Properties;
            }
        }

        public override string TitleText
        {
            get
            {
                string propString = (Properties == null) ? "0 props" : String.Format("{0} props", Properties.Count);

                return string.Format("{0} ({1})", propString, Properties.BuildList((i) => i.Identifier).MaxLength(30, true));
            }
        }

        public void UpdatePropertyValue(string prop, object newValue)
        {
            if (Properties == null)
                return;

            var propertyFound = Properties.FirstOrDefault((p) => p._identifier.Equals(prop, StringComparison.OrdinalIgnoreCase));
            propertyFound.Value = newValue;
        }

        public void BindToPropertyData(PropertyData prop)
        {
            Properties = prop.Props.AllItems.ToObservable();
        }

        public ShowPropertiesControl()
        {
            InitializeComponent();
        }

        public void SaveProps()
        {
            if (Owner == null)
            {
                DataAccess.CurrentlyPlaying.StoreThingAsync();
            }
            else
            {
                Owner.StoreThingAsync();
            }
        }

        private void btnAdd_Click(object sender, RoutedEventArgs e)
        {
            string propName = txtAdd.Text;
            IdentifierAndValue newProp = new IdentifierAndValue(propName, string.Empty);
            Properties.Add(newProp);
            if (Owner == null)
            {
                DataAccess.CurrentlyPlaying.ThingProperties.AddProperty(newProp.Identifier, newProp.Value);
            }
            else
            {
                (Owner as IHasPropertyData).ThingProperties.AddProperty(newProp.Identifier, newProp.Value);
            }
            SaveProps();
            UpdateBindings();
        }

        private void lstProps_Loaded(object sender, RoutedEventArgs e)
        {
            FrameworkElement t = sender as FrameworkElement;
            t.StretchListBox();
            Owner = DataVisualizer.Owner;
        }

        private void lstProps_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
        }

        public bool avoidRecurse = false;

        private void WrapPanel_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            // HEREHERE - not working correctly - refactor/clean up
            //if (avoidRecurse)
            //    return;

            //avoidRecurse = true;
            //WrapPanel wrap = sender as WrapPanel;

            //WindowContainer wc = this.FindParent<WindowContainer>();

            //if (wrap.Height != wc.ActualHeight - 26)
            //    wrap.Height = wc.ActualHeight - 26;

            //avoidRecurse = false;
        }

        private void WrapPanel_Loaded(object sender, RoutedEventArgs e)
        {
            WindowContainer wc = this.FindParent<WindowContainer>();
            
            if (wc != null)
                lstProps.ForEachRecursive<WrapPanel>((w) => w.Height = wc.ActualHeight - 44, null);
        }

        private void Image_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            Image img = (sender as Image);
            string identifier = img.Tag as string;

            Properties.Remove(true, (item) => item.Identifier.Equals(identifier, StringComparison.OrdinalIgnoreCase));

            if (Owner == null)
            {
                DataAccess.CurrentlyPlaying.ThingProperties.Remove(identifier);
            }
            else
            {
                (Owner as IHasPropertyData).ThingProperties.Remove(identifier);
            }            
        }

        private void txtAdd_LostFocus(object sender, RoutedEventArgs e)
        {
            FocusHandler.InTextField = false;
        }

        private void txtAdd_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            FocusHandler.InTextField = true;
        }
    }
}
